home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-29 | 66.0 KB | 2,554 lines |
- Newsgroups: comp.sources.unix
- From: alexj@equinox.unr.edu (Jack Alexander)
- Subject: v25i140: ils - interactive "ls" and browser
- Sender: unix-sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: alexj@equinox.unr.edu (Jack Alexander)
- Posting-Number: Volume 25, Issue 140
- Archive-Name: ils
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: MANIFEST Makefile README get.c get.h ils.1 ils.c ils.h
- # input.c main.c parse.c wildmat.c
- # Wrapped by vixie@cognition.pa.dec.com on Sat Feb 29 20:30:04 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(88 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- MANIFEST
- Makefile
- README
- get.c
- get.h
- ils.1
- ils.c
- ils.h
- input.c
- main.c
- parse.c
- wildmat.c
- END_OF_FILE
- if test 88 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(524 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# Makefile for ils
- X#
- CFLAGS = -D$(SYSTEM) -DNODEBUG -g
- X# for SYSTEM, make it SYSTEMV for System V and BSD for Berkely.
- SYSTEM = SYSTEMV
- X
- CC = cc
- X
- SRCS = main.c ils.c parse.c get.c input.c wildmat.c ils.h get.h
- X
- MANIFEST = Makefile README $(SRCS)
- X
- OBJS = main.o ils.o parse.o get.o input.o wildmat.o
- X
- all: ils
- X
- clean:
- X rm -f *.o
- X rm -f ils
- X
- ils: $(OBJS)
- X $(CC) $(OBJS) -o ils -lcurses -ltermcap
- X
- main.o: main.c ils.h
- X
- ils.o: ils.c ils.h
- X
- parse.o: parse.c
- X
- get.o: get.c get.h
- X
- input.o: input.c ils.h
- X
- wildmat.o: wildmat.c
- END_OF_FILE
- if test 524 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(3079 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- AUTHOR: Jack Alexander
- DATE OF LAST MODS: 1/11/91
- ANY COMMENTS OR REQUESTS FOR CHANGES WILL BE GREATFULLY ACCEPTED.
- X----------------------------------------------------------------------
- X(c) 1991 by Jack Alexander
- NO WARRANTY OF ANY KIND IS GIVEN WITH THIS PROGRAM, EVEN FOR
- XFITNESS OF PURPOSE
- X----------------------------------------------------------------------
- X
- ILS - Interactive "ls" and browser for UNIX systems.
- X
- This has been tested on BSD-ish and System V machines from several
- vendors including Sun, NCR, AT&T, and NeXT (previous version).
- X
- ils is "interactive ls", a utility to users to easily move around
- a directory tree and perform operations on objects in the directories.
- XEach user can define their own actions based on key-sequences.
- X
- The number of built-in commands has been kept to a minimum intentionally.
- The idea is to allow total flexibility by allowing people to
- use the same tools they've used for years (little shell scripts, etc),
- and to just offer them a more efficient, user-friendly way to do it.
- I know that this has been done before, but I didn't like the
- others ones that much because they were to specific and limiting.
- With ils, you can have as powerful or as "safe" a tool as you like,
- varying by user.
- X
- The operations available are defined by the user in $HOME/.ils
- in a manner as described in the file ils.1 file which is part
- of this release.
- X
- ils can really replace the use of the shell almost entirely
- for many users (I use it myself quite a bit -- I guess that's why
- I wrote it).
- X
- NOTE:
- I recommend that you always use the -F option, as it certainly makes
- identification of directories easy (puts '/' after each directory).
- This can be automatically done by linking ilf to ils, then just using
- the name ilf instead of ils.
- X
- INPUT:
- string input is done using a getstring I wrote a few years back. It's
- a little odd, as it was written for people that don't have any vi
- experience, as each key has a specific function, and you are always
- in insert mode. Editing instructions can be found in ils.1.
- X
- OVERVIEW:
- X
- The user (or administrator) has a file called .ils in their $HOME
- directory. A sample file might be:
- X
- X# This is a sampel .ils file
- help: man ils
- X
- m: more $file
- X
- V: vi $file
- X
- M: make $input(Make what (RETURN for default)? )
- X
- mv: mv $file $input(Rename '$file' to: )
- X
- XF: file $file
- X
- L: if(latex $prefix);then if(dvijep $prefix);then lpr -B $prefix.jep;fi;fi
- X
- rm: rm $file
- X
- X---------------------- end of example file ------------------
- X
- In the above file, key sequences "help", "m", "M", "mv", "F", "L", "rm",
- and "V" are given actions.
- X
- X$file is a built-in ils variable (see ils.1) that always contains the
- currently selected file (the one pointed at by the cursor). $prefix,
- and $input are also special variables, and there are others.
- X
- Anyway, if any of the key sequences are eneterd through the keyboard,
- and then ENTER or RETURN is pressed, the action defined for
- the key sequences in executed, a line at a time, via system(3) calls.
- You can multiple action lines for each key sequence, but the example
- doesn't contain any.
- END_OF_FILE
- if test 3079 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'get.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'get.c'\"
- else
- echo shar: Extracting \"'get.c'\" \(4715 characters\)
- sed "s/^X//" >'get.c' <<'END_OF_FILE'
- X/* %W% general getstring routine */
- X/* author: Jack Alexander - this routine may be freely distibuted */
- X#include <curses.h>
- X#include "get.h"
- X
- get_num(x,y,digits,low,high,number)
- int x,y,digits,low,high,*number;
- X{
- X char buf[80];
- X int retval;
- X
- X buf[0]='\0';
- X noecho();
- X raw();
- X while(1)
- X switch(getst(digits,x,y,buf,digits+1,NULL,NUM_ONLY,NULL)) {
- X case GET_ESCAPE:
- X return(GET_ESCAPE);
- X case GET_DOWN:
- X case GET_RETURN:
- X retval=atoi(buf);
- X if(retval < low || retval>high)
- X break;
- X *number = retval;
- X echo();
- X noraw();
- X return(0);
- X default:
- X break;
- X }
- X}
- X
- X/* a few hints... */
- X/* idx = current index into string */
- X/* cx = current screen x position */
- X/* cy = current screen y position */
- X/* ix = initial screen x (upon call, where cursor is requested to be placed) */
- X/* iy = initial screen y " " " ... */
- X/* fw = field width */
- X/* mx = max length of string */
- X/* sl = string length */
- X/* valid = string of acceptable characters within the type passed in gettype */
- X/* if NULL, then all type of characters passed in gettype are allowed */
- X
- int idx, cx, cy, ix, iy, fw, mx, sl, rcode;
- X
- getst(len,sx,sy,str,fl,retlen,gettype,valid)
- int len, sx, sy, fl, *retlen, gettype;
- char *str, *valid;
- X{
- X int c;
- X
- X
- X rcode = INITIAL;
- X idx=0;
- X cx=ix=sx;
- X cy=iy=sy;
- X mx = len;
- X fw = fl;
- X str[mx]='\0';
- X sl=strlen(str);
- X if(sl!=0) {
- X idx =sl; /* place cursor at string's end */
- X cx +=sl;
- X }
- X#ifdef undef
- X init();
- X#endif
- X while(1) {
- X if(gettype==SHOW) { /* want only to display the string */
- X drawstr(str,0); /* draw the string */
- X#ifdef undef
- X de_init();
- X#endif
- X return;
- X }
- X drawstr(str,1); /* draw the string */
- X c=getch()&0x7f;
- X switch(c) {
- X case GET_CLEAR:
- X clearall(str);
- X break;
- X case GET_ESCAPE:
- X rcode=GET_ESCAPE;
- X break;
- X case GET_UP:
- X rcode=dec_y_pos();
- X break;
- X case GET_DOWN:
- X rcode=inc_y_pos();
- X break;
- X case GET_LEFT:
- X rcode=dec_x_pos();
- X break;
- X case GET_RIGHT:
- X rcode=inc_x_pos(1);
- X break;
- X case GET_DELETE:
- X case GET_DELETE2:
- X remove_char(str);
- X break;
- X case GET_TAB:
- X case GET_RETURN:
- X rcode = GET_RETURN;
- X break;
- X default:
- X switch(gettype) {
- X case NUM_ONLY: /* numbers only (0-9) */
- X if(c>='0' && c<='9')
- X if(in(c,valid))
- X add_char(str,c);
- X break;
- X case LETTER_ONLY:
- X /* letters a-z and A-Z, and ' ' only */
- X if(c==' ' || (c>='a' && c<='z') || (c>='A' && c<='Z'))
- X if(in(c,valid))
- X add_char(str,c);
- X break;
- X case ALL_ALPHA:/* any printable chars */
- X if(c>=' ' && c<=0x7f)
- X if(in(c,valid))
- X add_char(str,c);
- X break;
- X default:
- X if(c>=' ' && c<=0x7f)
- X add_char(str,c);
- X break;
- X }
- X break;
- X }
- X if(rcode != INITIAL) {
- X#ifdef undef
- X de_init();
- X#endif
- X if(retlen != NULL)
- X *retlen = sl;
- X return(rcode);
- X }
- X }
- X}
- X
- dec_y_pos()
- X{
- X if(!idx)
- X return(GET_UP);
- X if(iy >= cy) {
- X idx = 0;
- X cx = ix;
- X return(INITIAL);
- X }
- X idx -= fw;
- X cy--;
- X return(INITIAL);
- X}
- X
- inc_y_pos()
- X{
- X if(idx>=mx-1 || idx==sl)
- X return(GET_DOWN);
- X if(idx+fw >= mx) {
- X cx += mx-idx - (mx-sl);
- X idx += mx-idx - (mx-sl);
- X#ifdef undef
- X cx += (mx - idx -fw);
- X idx += (mx - idx - fw);
- X#endif
- X return(INITIAL);
- X }
- X if(idx+fw > sl) {
- X cx += sl - idx;
- X idx += sl - idx;
- X return(INITIAL);
- X }
- X idx += fw;
- X cy++;
- X return(INITIAL);
- X}
- X
- inc_x_pos(flag)
- int flag;
- X{
- X if(flag && idx==sl)
- X return(GET_RIGHT);
- X if(idx == mx)
- X return(GET_RIGHT);
- X cx++;
- X idx++;
- X if(cx >= (ix+fw)) {
- X cx = ix;
- X cy++;
- X }
- X return(INITIAL);
- X}
- X
- dec_x_pos()
- X{
- X if(idx==0)
- X return(GET_LEFT);
- X idx--;
- X cx--;
- X if(cx < ix) {
- X cx = fw+ix-1;
- X cy--;
- X }
- X return(INITIAL);
- X}
- X
- add_char(str, c)
- char *str;
- char c;
- X{
- X register int i;
- X
- X if(inc_x_pos(0)!=INITIAL)
- X return;
- X for(i=mx-1;i>=idx;i--)
- X str[i]=str[i-1];
- X str[idx - 1] = c;
- X if(sl!=mx)
- X sl++;
- X}
- X
- remove_char(str)
- char *str;
- X{
- X register int i;
- X
- X if(idx >= sl) { /* remove char behind cursor */
- X if(dec_x_pos()!=INITIAL)
- X return;
- X str[sl-1]='\0';
- X }
- X else
- X for(i=idx;i<mx;i++)
- X str[i]=str[i+1];
- X sl--;
- X}
- X
- drawstr(str,refr)
- char str[];
- int refr;
- X{
- X int i, j, s, yo;
- X
- X s=sl;
- X move(iy,ix);
- X for(i=0,yo=1;i<mx;) {
- X if(i>=s) {
- X addch('.');
- X i++;
- X }
- X else if((s-i) < fw) {
- X printw("%s",&str[i]);
- X i += s-i;
- X }
- X else {
- X for(j=0;j<fw;j++)
- X addch(str[i++]);
- X }
- X if((i % fw)==0) {
- X move(iy + yo,ix);
- X yo++;
- X }
- X }
- X move(cy,cx);
- X if(refr)
- X refresh();
- X}
- X
- init()
- X{
- X noecho();
- X raw();
- X}
- X
- de_init()
- X{
- X noraw();
- X echo();
- X}
- X
- in(ch,allow)
- char ch, allow[];
- X{
- X register int i;
- X
- X if(allow == NULL)
- X return(1);
- X for(i=0;i<strlen(allow);i++)
- X if(ch==allow[i])
- X return(1);
- X return(0);
- X}
- X
- clearall(str)
- char str[];
- X{
- X sl=idx=0;
- X cx=ix;
- X cy=iy;
- X str[0]='\0';
- X}
- END_OF_FILE
- if test 4715 -ne `wc -c <'get.c'`; then
- echo shar: \"'get.c'\" unpacked with wrong size!
- fi
- # end of 'get.c'
- fi
- if test -f 'get.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'get.h'\"
- else
- echo shar: Extracting \"'get.h'\" \(797 characters\)
- sed "s/^X//" >'get.h' <<'END_OF_FILE'
- X/* defines for my getstring routine */
- X/* %W% */
- X
- X#define INITIAL 0
- X#define GET_CLEAR 0x03 /* control c */
- X#define GET_UP 0x0b /* control k */
- X#define GET_DOWN 0x0a /* control j */
- X#define GET_LEFT 0x08 /* control h */
- X#define GET_RIGHT 0x0c /* control l */
- X#define GET_TAB 0x09 /* control i */
- X#define GET_RETURN 0x0d /* control m */
- X#define GET_DELETE 24 /* control x */
- X#define GET_DELETE2 0x7f /* delete key on most terminals */
- X#define GET_ESCAPE 0x1b /* escape */
- X
- X/* types of characters that can be specified for getstring input */
- X#define SHOW 0 /* only show the string, don't ask for input */
- X#define NUM_ONLY 1 /* only numeric characters 0-9 */
- X#define LETTER_ONLY 2 /* only letters a-z, A-Z and space (' ') */
- X#define ALL_ALPHA 3 /* all printable ascii characters are permitted */
- END_OF_FILE
- if test 797 -ne `wc -c <'get.h'`; then
- echo shar: \"'get.h'\" unpacked with wrong size!
- fi
- # end of 'get.h'
- fi
- if test -f 'ils.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ils.1'\"
- else
- echo shar: Extracting \"'ils.1'\" \(7789 characters\)
- sed "s/^X//" >'ils.1' <<'END_OF_FILE'
- X.PU
- X.TH ILS 1 local
- X.SH NAME
- ils \- interactive directory browser and visual shell
- X.SH SYNOPSIS
- X.ll +8
- X.B ils \[-aFeTr<rows>c<columns> \[title\]\] \[ pattern1 pattern2 \.\.\. patternN \]
- X.ll -8
- X.br
- X.SH DESCRIPTION
- X.B ils
- was orginally just a driectory browsing utility to allow users
- to move around the system, descending into directories through
- a visually-oriented interface.
- X
- Since the original implementation, the functionality of
- X.B ils
- has been expanded to allow operations to be performed on the files in the
- directories currently being examined. Each user can define their own set of
- operations using built-in variables, environment variables, as well as
- keyboard input. By creating a file, ``.ils" in the $HOME directory,
- each user can define what sequence of keys invokes a set of shell
- operations.
- X
- There are several options, some of which corresponds to the option of
- the same name in the
- X.B ls(1)
- command:
- X.TP
- X.BI \-a
- List all entries; usually `.', `..' and all files that start with a `.'
- are suppresed. This is the default if the last character of the name
- of the program is an `a' (i.e., linking ila to ils).
- X.TP
- X.BI \-F
- Cause directories to be marked with a trailing `/' and executable files
- to be marked with a trailing `*'. This is the default if the last
- character of the name of the program is a `f' (i.e., linking ilf to ils).
- X.TP
- X.BI \-e
- XEcho all commands as they are executed.
- X.TP
- X.BI \-T\ \<title\>
- Print a title on top of the window or screen.
- X.TP
- X.BI \-r
- Change the vertical size of the ils window from the default. The default is the
- size of the screen upon calling ils. If using this option, the
- number of rows must immediately follow, with no white space (i.e., ils -r10).
- X.TP
- X.BI \c
- Change the horizontal size of the ils window from the default. The default
- is the size of the screen upon calling ils. If using this option, the
- number of columns must immediately follow, with no white space (i.e., ils -r60).
- X
- X.SH WILDCARDING
- Patterns can be used in to match files, just as in ls(1). To
- pass a pattern to ils, and to avoid the shell from
- expanding it prior to invoking ils, the user can surround
- the pattern with quotes (i.e., 'ils "*.c"' instead of ils *.c).
- This will insure that the pattern match is done on every directory
- descended into during the execution of ils. Otherwise, if no
- quotes are used, the shell will expand the wildarding and pass ils
- all filenames that match the pattern in the current working directory.
- Any directory descended into that do not contain any files of the same name
- will appear to the user as an empty directory.
- X
- X.B ils
- wildcarding works exactly the same as sh(1), csh(1), and ksh(1)
- wildcarding (thanks to Rich Salz for the wildcarding routine).
- X
- X.SH THE .ils FILE
- XEach user can set up their own .ils file in their home ($HOME) directory
- to define their own key sequences and corresponding actions related to
- those key sequences. The .ils file has the following format:
- X
- X.nf
- key_sequence: command line 1
- X command line 2
- X ...
- X command line n
- X.fi
- X
- This tells
- X.B ils
- that when the key sequence is entered, execute the shell commands
- in command lines 1 through n. One current limitation
- X.B ils
- has is that each command line is executed seperately, so that
- no interdependent lines can be used. A call to system(3) is made on
- each line, so a new shell comes into existance for each line.
- Any environmental changes made such as shell variable assignment
- or change of working directory are lost after each command.
- You can, however, have multiple shell commands on one line by using
- semicolons delimiting seperate commands.
- X
- All lines that have a `#' character as the first character are
- assumed to be comments and are skipped.
- X.SH USING ils
- upon execution, the user will see a listing of the directory,
- very similar to the output of the
- X.B ls(1)
- command. On the top line is the path of the current directory.
- If possible,
- X.B ils
- will display the full path of the current working directory. If the
- path exceeds the width of the screen or window, it will be truncated.
- Since the right-most characters of a pathname are usually of the most interest,
- the truncation is done at the left end. As many characters as will fit
- are shown, and the path is preceeded by "...".
- X
- One file is always the "current file", it is pointed at by the
- X.B ils
- cursor `>'. To change the current file, there are cursor movement
- keys. The defaults are h,j,k and l (as in vi(1)). If a directory
- has been made the current file, the user can descend into the directory
- by pressing the RETURN or ENTER key. Once the user has descended into
- a directory the directory becomes the current working directory. The
- current path on the top line will be updated, and the contents of the
- directory will be shown on the screen.
- X
- The user can also ``force" a command from the keyboard by pressing
- the ':' key. This will prompt the user for a line of input which will
- be scaned for variable substitution, then executed via a call to system(3).
- This can be useful in that it makes it so that the user rarely has to
- leave ils to perform a command (i.e, ":rm *.o" will invoke a shell
- and remove all file ending in ".o"; ":more $file" will invoke a shell
- and display the cuurently selected file via the more(1) command).
- X
- To go back up one level (i.e., cd ..), press ESCAPE.
- X
- To exit ils, press control-D.
- X
- X.SH KEYBOARD INPUT and STRING EDITING
- When entering string from the keyboard, there is one important
- thing to remember: you are always in insert mode.
- The string editing routines in
- X.B ils
- use the following keys:
- X.TP
- X.BI ESCAPE
- Abort editing this string
- X.TP
- X.BI control-x
- Delete a character
- X.TP .BI
- X.BI control-c
- Clear entire string
- X.TP
- X.BI left-arrow
- Go left one character within the string
- X.TP
- X.BI ENTER (or RETURN)
- The first ENTER puts you at the end of the string, the second ENTER
- will pass the string back to ils for processing, and terminate the
- string edit. If you are already on the last character in the string,
- then the first press of ENTER will enter the string.
- X
- All of the command keys used in editing can be easily changed by modifying
- the file "ils.h", then re-making ils. In a later release, it is hoped that
- each user can define their editing key within their ".ils" file.
- X
- X.SH VARIABLES AND BUILT-IN COMMANDS
- X.B ils
- has several variables and commands built-in:
- X.TP
- X.BI $file
- the name of the file currently selected
- X.TP
- X.BI $prefix
- the prefix (all characters up to the first `.') of the
- file currently selected
- X.TP
- X.BI $path
- the current directory being viewed
- X.TP
- X.BI $all_files
- all files in the directory being viewed
- X.TP
- X.BI $input(prompt)
- value typed in from keyboard after user is prompted with the string
- contained in prompt (variable names can be used in contructing prompt)
- X.TP
- X.BI $ENVIRONMENT_VARIABLE
- the value of any environment variable can be used (i.e., $HOME will
- be substituted with the value of $HOME in the user's environment).
- X.B ils
- will use it's own variable values before checking for any existing
- environment variables. This means that is the user wants to
- use the value of the variable $file from his environment,
- X.B ils
- will use the name of the current file instead, since $file is
- a built-in variable.
- X
- X.SH SAMPLE .ils FILE
- X
- X
- X.nf
- X# This is a sample .ils file
- X#
- cc: cc $file
- X
- RM: rm $file
- X
- V: vi $file
- X
- X# make, can change default by entering an alernative
- X# (i.e., "make install")
- M: make $input(Make what (RETURN is default)? )
- X
- X# rename the file
- mv: mv $file (Rename $file to: )
- X
- X# LateX a file and print it
- L: latex $prefix
- X dvijep $prefix
- X lpr -b $prefix.jep
- X
- X# look at my definition file
- defs: more $HOME/.ils
- X.fi
- X
- X.SH RELEASE NOTES
- X
- X.PP
- X.SH "AUTHOR"
- Jack Alexander, (jack@jimi.cs.unlv.edu), (jack@equinox.unr.edu)
- X.SH "BUGS"
- No known bugs
- END_OF_FILE
- if test 7789 -ne `wc -c <'ils.1'`; then
- echo shar: \"'ils.1'\" unpacked with wrong size!
- fi
- # end of 'ils.1'
- fi
- if test -f 'ils.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ils.c'\"
- else
- echo shar: Extracting \"'ils.c'\" \(25940 characters\)
- sed "s/^X//" >'ils.c' <<'END_OF_FILE'
- X/**************************************************************************
- X * ils - interactive "ls" library for ascii terminals.
- X *
- X * Subroutine ils expects variable "rows", and "cols" to be set prior to
- X * calling. rows should contain the verticle size of the window to
- X * be used, and cols should contain horizontal size (in characters).
- X *
- X *
- X * Author: Jack Alexander
- X * jack@marley
- X *
- X */
- X#include "ils.h"
- X
- X#include <curses.h>
- X#include <stdio.h>
- X#include <sys/dir.h>
- X#include <fcntl.h>
- X#include <errno.h>
- X
- X#include "get.h" /* need key definitions from getstring routine */
- X
- extern char *pnam; /* program name */
- X
- int a_num, a_ind; /* work variables for argument processing */
- int syms=0; /* number of symbols in table */
- struct symbol *symtab[MAX_SYMBOLS]; /* symbol table */
- char *args[ILS_MAX_ARGS]; /* argument list */
- int modes; /* hold behavioral data */
- X
- char cur_path[MAXPATH]; /* current path */
- X
- X
- X/* interactive directory browser -- main routine
- X**
- X** variable pattern in a two dimensional array containing all of the patterns
- X** to use for pattern matching. If pattern[0] == NULL, then no
- X** patterns are used, and all files are shown.
- X**
- X** variable path is a string containing the path of the directory from which
- X** browsing will begin (typically, same as pwd(1)).
- X**
- X** ulx, uly, lrx, and lry are the coordinates (in screen coordinates where
- X** units are characters.
- X**
- X** m is an integer which may contain any behavioral charactaristics.
- X** various bits, as described in ils.h can be ored into this variable to
- X** change the behavior of ils.
- X**
- X** title is a string which is displayed on the top line of the window. If
- X** title is NULL, then no title is shown, and you get an extra line for
- X** editing.
- X**/
- ils(pattern,path,ulx,uly,lrx,lry,m,title)
- char *pattern[],*path,*title;
- int ulx, uly, lrx, lry, m;
- X{
- X struct d_entry *top; /* the very top of the known directory tree */
- X
- X modes = m; /* makes user defined modes global */
- X top = (struct d_entry *) NULL; /* haven't read any directories yet */
- X clear();
- X read_ils_defines(); /* read this user's definitions */
- X read_directory(pattern,path,&top); /* read in current directory */
- X edit_directory(pattern,path,&top,ulx,uly,lrx,lry,title); /* do it */
- X}
- X
- X/* read_ils_defines() looks and the ".ils" file for the user. This file
- X contains all user-specific key sequences and correspoding actions for
- X the key sequences. */
- read_ils_defines()
- X{
- X char *getenv(), *a, dummy[MAXPATH];
- X FILE *fopen(), *fp;
- X int lnum=0;
- X
- X a=getenv("HOME"); /* get path to user's home directory */
- X sprintf(dummy,"%s/.ils",a); /* set up path to the .ils file */
- X if((fp=fopen(dummy,"r"))==NULL)
- X return; /* no ".ils" file in home directory */
- X while(fgets(dummy,MAXPATH,fp)!=NULL) {
- X lnum++; /* line number counter */
- X if(dummy[0]=='#')
- X continue; /* a comment line */
- X parse_line(dummy,lnum); /* enter into symbol table */
- X }
- X fclose(fp);
- X}
- X
- X#ifdef BSD
- X/******
- X * Berkeley UNIX version. read directory reads all files in the current
- X * directory.
- X */
- read_directory(pattern,path,dptr)
- char *pattern[],path[];
- struct d_entry **dptr;
- X{
- X DIR *dp, *opendir();
- X struct direct *dirptr, *readdir();
- X
- X if(chdir(path)<0)
- X return; /* can't change to desired directory */
- X if((dp=opendir("."))==NULL)
- X return; /* can't open the directory file itself */
- X while((dirptr=readdir(dp))!=NULL) /* end of directory */
- X add_entry(pattern,dirptr->d_fileno,dirptr->d_name,dptr);
- X closedir(dp);
- X}
- X#endif BSD
- X
- X#ifdef SYSTEMV
- X/* SYSTEM V Unix version of the read_directory routine. */
- read_directory(pattern,path,dptr)
- char *pattern[],path[];
- struct d_entry **dptr;
- X{
- X struct direct d;
- X int fd;
- X
- X if(chdir(path)<0) /* can't change to the desired directory */
- X return;
- X if((fd=open(".",O_RDONLY))<0) /* can't open the directory file */
- X return;
- X while(read(fd,&d,sizeof(struct direct)) == sizeof(struct direct))
- X add_entry(pattern,d.d_ino,d.d_name,dptr); /* add file */
- X close(fd);
- X}
- X#endif SYSTEMV
- X
- X/* showpath displays the string in "path" on the top line of the window.
- X The top line is defined in ulx, ily. Only as much of the path as
- X can be seen is displayed, the rest is cust out. */
- showpath(path,ulx, uly, lrx, lry)
- char path[];
- int ulx, uly, lrx, lry;
- X{
- X int l;
- X char dummy[80];
- X
- X standout(); /* invert the line */
- X move(uly,ulx); /* move to top line of the window */
- X if((l=strlen(path))>(lrx-uly-1)) { /* is string too long? */
- X /* if string is too long, truncate it. preceed all truncated
- X paths with "..." to show user that the path was indeed
- X truncated. */
- X sprintf(dummy,"...%c%d.%ds",'%',(lrx-ulx-3),(lrx-ulx-3));
- X printw(dummy,path+(l-(lrx-ulx-3))); /* print path */
- X }
- X else /* string is not too long, just print it */
- X printw(path);
- X standend(); /* end inverted mode */
- X clrtoeol(); /* get rid of standend char on some types of terminals */
- X}
- X
- X/* display an error message on the top line of the window, wait for RETURN
- X key to be pressed so that user can acknowledge the error */
- ils_error(msg,ulx,uly,lrx,lry)
- char msg[];
- int ulx, uly, lrx, lry;
- X{
- X int l;
- X char dummy[80];
- X
- X standout(); /* all errors in inverse mode */
- X move(uly,ulx); /* go to top line */
- X sprintf(dummy,">> %s << Press RETURN...",msg);
- X if((l=strlen(dummy))>(lrx-uly-1)) { /* does message need truncation? */
- X if(strlen(msg) > (lrx-uly-1)) {
- X /* truncate the message. Preceed truncated with "..." */
- X sprintf(dummy,"...%c%d.%ds",'%',(lrx-ulx-3),(lrx-ulx-3));
- X printw(dummy,msg+(l-(lrx-ulx-3)));
- X
- X }
- X else
- X strcpy(dummy,msg); /* no truncation needed */
- X }
- X printw(dummy);
- X standend(); /* end inverse mode */
- X refresh();
- X ils_wait_key(ILS_ENTER); /* wait for RETURN key to be pressed */
- X}
- X
- X/* wait for key (passed in variable 'c') to be pressed. Keep asking
- X for more keys until the one waited for is pressed. */
- ils_wait_key(c)
- int c;
- X{
- X while((getch()&0x7f)!=c);
- X}
- X
- X/* edit a directory, using a rectangle in the screen with (ulx, uly) as
- X the coordinates of the upper-left corner of the rectangle, and
- X (lrx, lry) as the lower-right corner of the rectangle. title is
- X a character string that will be printed in the top line of the rectangle,
- X unless a NULL is passed, in which case nothing is printed, and you
- X have another line to use as part of the directory. */
- X
- edit_directory(pattern,path,dptr,ulx,uly,lrx,lry,title)
- char *pattern[],path[];
- struct d_entry **dptr;
- int ulx, uly, lrx, lry;
- char *title;
- X{
- X static int level=0;
- X char newpath[80], trailer, *p, line[MAXPATH], this_dir[MAXPATH],
- X last_active[MAXPATH];
- X struct d_entry *cur, *t, *active_list[ILS_MAX_ENTRIES];
- X int height, width, widest, entries, i, j, horiz_fit, vert_fit,
- X x, y, more_line, first_visible, orig_uly,
- X column_height, cur_entry, state, next_state, c,
- X last_x, last_y, z, up_x, up_y, down_x, down_y,
- X done, new_entries, low, high, middle;
- X
- X clear();
- X raw(); /* need characters AS THEY ARE PRESSED */
- X noecho(); /* don't show user's input */
- X
- X orig_uly = uly;
- X if(title != (char *)NULL) /* is there a title? */
- X uly++; /* account for title line */
- X uly++; /* account for "current directory" line */
- X
- X height = lry - uly; /* height of window */
- X width = lrx - ulx; /* width of window */
- X
- X strcpy(cur_path,path); /* make path globally known */
- X
- X level++; /* count the levels down */
- X
- X state = ILS_INITIAL;
- X next_state = ILS_INITIAL2;
- X cur_entry = 0;
- X
- X while(1) { /* loop will end with an exit() call */
- X switch(state) {
- X case ILS_INITIAL:
- X cur = *dptr; /* get all entries in directory into a sorted list */
- X widest = 6; /* default longest string length */
- X entries = first_visible = 0;
- X /* loop through and find the longest filename in the list */
- X while(cur != (struct d_entry *)NULL) {
- X if((i=strlen(cur->name)) > widest)
- X widest = i; /* found a longer string */
- X active_list[entries++] = cur;
- X cur = cur->next; /* get next in list */
- X }
- X /* get number of strings that can fit => how many columns */
- X horiz_fit = width / (widest+2);
- X column_height = entries / horiz_fit + ((entries%horiz_fit)==0? 0:1);
- X vert_fit = lry-uly; /* how many can fit verticall into window */
- X if(vert_fit > column_height)
- X vert_fit = column_height; /* safeguard */
- X
- X state = next_state;
- X break;
- X
- X case ILS_INITIAL2:
- X if(!entries) { /* is this an empty directory? */
- X showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
- X ils_error("EMPTY DIRECTORY",ulx,orig_uly,lrx,lry);
- X level--;
- X return; /* empty: allow no editing */
- X }
- X state = ILS_TOTAL_DRAW; /* redraw screen */
- X break;
- X
- X case ILS_FIND_CURSOR: /* locate best place for cursor */
- X done = 0;
- X low = 0; /* base value for binary search */
- X high = entries; /* high value for binary search */
- X /* binary search to position where the cursor should be */
- X while(!done) { /* binary search to the place to put cursor */
- X middle = (low+high)/2;
- X i = strcmp(last_active,active_list[middle]->name);
- X if(i==0)
- X done = 1; /* found entry! */
- X if(i<0) {
- X if(middle==high) /* found where to put cursor */
- X done=1;
- X else
- X high = middle; /* try lower half */
- X }
- X else {
- X if(middle==low) /* found where to put cursor */
- X done=1;
- X else
- X low = middle; /* try upper half */
- X }
- X }
- X /* middle is now equal to entry number where cursor should be */
- X cur_entry = middle;
- X first_visible = 0; /* for now, top line shown is line 0 */
- X i = middle % column_height; /* get offset from top of column */
- X if(i>=vert_fit) /* is the active entry off the screen? */
- X first_visible = i-vert_fit+1;/* YES make it visible */
- X if(first_visible<0 || first_visible>=entries || first_visible>=vert_fit)
- X first_visible = i; /* safeguard */
- X if(first_visible >= entries) /* another safeguard */
- X first_visible;
- X state = ILS_INITIAL2;
- X break;
- X
- X case ILS_TOTAL_DRAW: /* redraw the whole window */
- X clear();
- X if(title != NULL) { /* is there a title to display? */
- X move(orig_uly,ulx);
- X clrtoeol();
- X printw("%s",title); /* display the title */
- X }
- X /* display the path either just below the title, or on top */
- X showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
- X case ILS_DRAW: /* show files in directory */
- X up_x=up_y=down_x=down_y= -1;
- X for(i=0,z=first_visible;i<horiz_fit;i++) {
- X for(j=0;j<vert_fit && z<entries;j++,z++) {
- X y=uly+j;
- X x=1+ulx+(width/horiz_fit)*i;
- X move(y,x);
- X if(!i)
- X clrtoeol();
- X if(!i && !j && first_visible) {
- X standout();
- X printw("< more",first_visible*horiz_fit+1);
- X standend();
- X up_x = x;
- X up_y = y;
- X }
- X else {
- X trailer=' ';
- X if(modes & ILS_F_TYPE) {
- X if(active_list[z]->stat.st_mode & 040000)
- X trailer='/';
- X else if(active_list[z]->stat.st_mode & 0100)
- X trailer='*';
- X }
- X printw("%s%c",active_list[z]->name,trailer);
- X
- X }
- X }
- X z+=column_height-vert_fit;
- X }
- X if((first_visible+vert_fit) < column_height) {
- X y=uly+vert_fit-1;
- X x=1+ulx+(width/horiz_fit)*(horiz_fit-1);
- X move(y,x);
- X standout();
- X printw("more >");
- X standend();
- X clrtoeol();
- X down_x = x;
- X down_y = y;
- X }
- X
- X refresh();
- X state = ILS_SHOW_CURSOR;
- X next_state = ILS_KEYBOARD;
- X break;
- X case ILS_SHOW_PATH:
- X showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
- X case ILS_MOVE_CURSOR:
- X move(last_y,last_x);
- X addch(' ');
- X case ILS_SHOW_CURSOR:
- X last_y=y=uly + cur_entry%column_height-first_visible;
- X last_x=x=ulx + (width/horiz_fit) * (cur_entry / column_height);
- X if((x+1)==up_x && y==up_y) {
- X first_visible--;
- X state = ILS_DRAW;
- X break;
- X }
- X if((x+1)==down_x && y==down_y) {
- X first_visible++;
- X state = ILS_DRAW;
- X break;
- X }
- X move(y,x);
- X addch('>');
- X move(y,x);
- X refresh();
- X state = next_state;
- X break;
- X case ILS_KEYBOARD:
- X switch((c=(getch()&0x7f))) {
- X case ILS_ESCAPE: /* go back up or QUIT! */
- X if(level==1)
- X state=ILS_ASCEND;
- X else
- X state = ILS_EXIT;
- X break;
- X case ILS_EXIT_KEY: /* QUIT NOW! */
- X ils_exit(1);
- X break;
- X case ILS_ENTER:
- X case ILS_RETURN: /* descend into a directory */
- X if(active_list[cur_entry]->stat.st_mode & 040000) {
- X if(strcmp(active_list[cur_entry]->name,".")==0) {
- X flash(); /* change to current directory */
- X break;
- X }
- X if(strcmp(active_list[cur_entry]->name,"..")==0) {
- X if(level==1)
- X state = ILS_ASCEND;
- X else
- X state = ILS_EXIT;
- X break;
- X }
- X if(path[1]=='\0')
- X sprintf(newpath,"/%s",active_list[cur_entry]->name);
- X else
- X sprintf(newpath,"%s/%s",path,active_list[cur_entry]->name);
- X strcpy(last_active,active_list[cur_entry]->name);
- X if(active_list[cur_entry]->contents == (struct d_entry *)NULL) {
- X read_directory(pattern,newpath,&(active_list[cur_entry]->contents));
- X }
- X else {
- X chdir(newpath);
- X strcpy(cur_path,newpath);
- X re_read_dir(pattern,&(active_list[cur_entry]->contents));
- X }
- X refresh();
- X edit_directory(pattern,newpath,&(active_list[cur_entry]->contents),ulx,orig_uly,lrx,lry,title);
- X chdir(path); /* back up */
- X strcpy(cur_path,path);
- X state = ILS_INITIAL;
- X if((new_entries=re_read_dir(pattern,dptr))!=entries)
- X next_state = ILS_FIND_CURSOR;
- X else
- X next_state = ILS_INITIAL2;
- X }
- X break;
- X case ILS_UP: /* move cursor up */
- X if(cur_entry==0 || (cur_entry%column_height)==0)
- X break; /* can't move up one */
- X cur_entry--;
- X y=uly+cur_entry%column_height-first_visible;
- X if(y<uly) {
- X state = ILS_DRAW;
- X first_visible--;
- X }
- X else {
- X state = ILS_MOVE_CURSOR;
- X next_state = ILS_KEYBOARD;
- X }
- X break;
- X case ILS_DOWN: /* move cursor down */
- X if(cur_entry==(entries-1) || (cur_entry%column_height)==column_height-1)
- X break; /* can't move down one */
- X cur_entry++;
- X y=uly+cur_entry%column_height-first_visible;
- X if(y>=lry) {
- X state = ILS_DRAW;
- X first_visible++;
- X }
- X else {
- X state = ILS_MOVE_CURSOR;
- X next_state = ILS_KEYBOARD;
- X }
- X break;
- X case ILS_RIGHT: /* move cursor right */
- X if(cur_entry+column_height >= entries)
- X break; /* can't move right */
- X else {
- X cur_entry+=column_height;
- X state = ILS_MOVE_CURSOR;
- X next_state = ILS_KEYBOARD;
- X }
- X break;
- X case ILS_LEFT: /* move cursor left */
- X if(cur_entry-column_height < 0)
- X break; /* can't move left */
- X else {
- X cur_entry-=column_height;
- X state = ILS_MOVE_CURSOR;
- X next_state = ILS_KEYBOARD;
- X }
- X break;
- X case ILS_REDRAW: /* redraw the screen */
- X case ILS_REDRAW_ALT: /* alternate character */
- X state = ILS_TOTAL_DRAW;
- X break;
- X case ILS_ENV: /* display symbol table */
- X display_symtab();
- X state = ILS_TOTAL_DRAW;
- X break;
- X case ILS_FORCE_KEYBOARD: /* force us into keyboard mode */
- X default:
- X if(keybd(c,ulx,orig_uly+(title==NULL? 0:1),lrx,lry,line)) {
- X strcpy(last_active,active_list[cur_entry]->name);
- X process_input(c,active_list,cur_entry,entries,line,ulx,orig_uly+(title==NULL? 0:1),lrx);
- X state = ILS_INITIAL;
- X if((new_entries=re_read_dir(pattern,dptr))!=entries)
- X next_state = ILS_FIND_CURSOR;
- X else
- X next_state = ILS_INITIAL2;
- X showpath(path,ulx,orig_uly+(title==NULL? 0:1),lrx,lry);
- X }
- X else
- X state = ILS_SHOW_PATH;
- X break;
- X }
- X break;
- X case ILS_ASCEND: /* up into a new directory */
- X if(path[1]=='\0') { /* at root (/) ? */
- X flash(); /* can't go up any higher! */
- X state = ILS_KEYBOARD; /* back to input mode */
- X break;
- X }
- X strcpy(newpath,path);
- X /* find the first '/' character from the right, then chop the
- X path from that point on. This is to make a path like:
- X /usr/local/bin
- X into
- X /usr/local
- X */
- X for(i=strlen(path)-1;i && newpath[i]!='/';i--);
- X if(i==0) { /* i==0 if we are one level down from root */
- X strcpy(newpath,"/"); /* make root the new path */
- X strcpy(this_dir,&(path[1]));
- X }
- X else {
- X newpath[i]='\0'; /* up one level in the path */
- X strcpy(this_dir,&(newpath[i+1]));
- X }
- X if(this_dir[0]=='\0') /* make sure not a null string */
- X break; /* a little safeguard */
- X cur = (struct d_entry *) NULL; /* ready to read a new dir */
- X read_directory(pattern,newpath,&cur); /* read it */
- X t = cur; /* find the entry in the new directory that
- X corresponds to this directory's name. */
- X strcpy(last_active,this_dir); /* for finding cursor pos */
- X for(cur = (*dptr);cur!=(struct d_entry *)NULL;) {
- X if(strcmp(cur->name,this_dir)==0) {
- X /* found it. assign contents to this entry */
- X cur->contents = (*dptr);
- X cur = (struct d_entry *) NULL;
- X }
- X else /* try next one */
- X cur = cur->next;
- X }
- X (*dptr) = t; /* make this the new "top of tree" pointer */
- X strcpy(cur_path,newpath); /* let globals know */
- X strcpy(path,newpath);
- X cur_entry = first_visible = 0;
- X state = ILS_INITIAL; /* make this the active one */
- X next_state = ILS_FIND_CURSOR;
- X break;
- X case ILS_EXIT: /* QUIT! */
- X move(last_y,last_x);
- X addch(' '); /* erase cursor */
- X level--; /* back up one level */
- X if(level==0) {
- X noraw();
- X echo();
- X }
- X return(1);
- X break;
- X }
- X }
- X}
- X
- X/* add an entry to a directory list.
- X** pattern is the array of search patterns as passed to ils()
- X** i is the inode number of this entry
- X** p is the name of this entry
- X** place the the pointer to the directory list (of d_entry's)
- X*/
- add_entry(pattern,i,p,place)
- long i;
- char *pattern[],*p;
- struct d_entry **place;
- X{
- X struct d_entry *t, *cur, *last;
- X int l, match;
- X struct stat st;
- X char *ps, *pd;
- X
- X if(i==0) /* if inode is 0, file was removed */
- X return;
- X if(stat(p,&st)<0) /* can't stat file, don't add it */
- X return;
- X if(p[0]=='.' && (modes&ILS_ALL)==0) /* is this a "." file? */
- X return; /* starts with '.', not in list all mode */
- X if(pattern[0]!=(char *)NULL) { /* if patterns are used, see if match */
- X for(l=match=0;pattern[l]!=(char *)NULL && match==0;l++) {
- X if(wildmat(p,pattern[l]))
- X match++; /* matches a pattern */
- X }
- X if(!match)
- X return; /* doesn't match any patterns */
- X }
- X
- X new_entry(&t,p,&st); /* get memory and assign values */
- X
- X if(*place == (struct d_entry *)NULL) /* empty list */
- X *place=t;
- X else {
- X /* loop through and decide where to place the new entry.
- X the list is a sorted doubly-linked list. */
- X cur = last = *place;
- X while(cur != (struct d_entry *)NULL) {
- X if(strcmp(p,cur->name) < 0) { /* insert before */
- X if(cur == *place) { /* at top of list */
- X t->next = *place;
- X cur->prev = t;
- X *place = t;
- X return;
- X }
- X else { /* in middle */
- X cur->prev->next = t;
- X t->prev = cur->prev;
- X cur->prev = t;
- X t->next = cur;
- X return;
- X }
- X }
- X else { /* check next name */
- X last = cur;
- X cur = cur->next;
- X }
- X }
- X if( cur == (struct d_entry *)NULL) { /* insert at end of list */
- X last->next = t;
- X t->prev = last;
- X }
- X }
- X}
- X
- X/* get a string from the keyboard, and process it based on defined keysequences.
- X** c is the first character (as entered in the mailine ils code above.
- X** if c is not a FORCE_KEYBOARD character, thenn it is inserted into
- X** the string passed to the string editing routine, as the first character
- X** of the user's string.
- X** leftx,upy,rightx,downy are screen coordinates of the window size,
- X** regarding the location of the upper-left and lower-right corners.
- X** line is a pointer to a string. This is where the keyboard input will
- X** be placed and thus passed back to the calling routine.
- X*/
- keybd(c,leftx,upy,rightx,downy,line)
- int leftx, upy, rightx, downy;
- char c, line[];
- X{
- X int l;
- X
- X if(c==ILS_FORCE_KEYBOARD) /* is this a FORCED KEY SEQUENCE? */
- X line[0]='\0';
- X else { /* if legal character, insert into line[] */
- X if(c<' ' || c >0x7f) /* out of range */
- X return;
- X line[0]=c;
- X line[1]='\0';
- X }
- X
- X if(rightx-leftx-7 < 2) /* see if we can fit the prompt */
- X return(0); /* no space on screen for input */
- X move(upy,leftx);
- X printw("Input: "); /* print the prompt */
- X l=getst(rightx-leftx-8,leftx+7,upy,line,rightx-leftx-7,&l,ALL_ALPHA,NULL);
- X if(l==GET_RETURN || l==GET_DOWN)
- X return(1);
- X return(0); /* probably ESCAPED out */
- X}
- X
- X/* free_contents() de-allocates the contents of the directory pointed at
- X** by p.
- X*/
- free_contents(p)
- struct d_entry *p;
- X{
- X if(p->next != (struct d_entry *)NULL) /* depth-first deallaocation */
- X free_contents(p->next);
- X if(p->contents != (struct d_entry *)NULL) /* get rid of contents */
- X free_contents(p->contents);
- X free(p); /* get rid of top node */
- X}
- X
- X/* re_read_dir() takes another look at the contents of a directory for
- X** changes in the contents or mode bits of the directory members.
- X** This is used when a directory is re-entered into, and we need to see
- X** if files were remove, added, or changed in any way.
- X**
- X** pattern is the array of search patterns as passed to ils() initially.
- X**
- X** dptr is the pointer to the contents of the directory last time it was
- X** examined.
- X*/
- re_read_dir(pattern,dptr)
- char *pattern[];
- struct d_entry **dptr;
- X{
- X char name[MAXPATH], *pd, *ps;
- X struct d_entry *tdptr,*t;
- X int i,inode,r,done,mxloop;
- X struct stat st;
- X long touch, time();
- X#ifdef BSD /* berkeley directories are different */
- X DIR *dp, *opendir();
- X struct direct *dirptr, *readdir();
- X
- X if(chdir(cur_path)<0)
- X return;
- X if((dp=opendir("."))==NULL)
- X return;
- X tdptr = *dptr;
- X touch = time((long *)0);
- X while((dirptr=readdir(dp))!=NULL) {
- X strcpy(name,dirptr->d_name);
- X inode = dirptr->d_fileno;
- X#endif BSD
- X
- X#ifdef SYSTEMV
- X struct direct d;
- X int fd;
- X
- X if(chdir(cur_path)<0)
- X return;
- X if((fd=open(".",O_RDONLY))<0)
- X return;
- X tdptr = *dptr;
- X touch = time((long *)0);
- X while(read(fd,&d,sizeof(struct direct)) == sizeof(struct direct)) {
- X strncpy(name,d.d_name,DIRSIZ);
- X name[DIRSIZ]='\0';
- X inode = d.d_ino;
- X#endif SYSTEMV
- X /* common entry-handling code */
- X
- X if(inode) /* if this file wasn't removed, stat it */
- X if(stat(name,&st)<0)
- X continue; /* can't stat? forget this one! */
- X if(name[0]=='.' && (modes&ILS_ALL)==0)
- X continue; /* skip this, not in 'list all' mode */
- X done=0;
- X mxloop=0;/* mxloop is a safeguard. It was used for
- X initial debugging, and can probably be removed */
- X while(!done && mxloop++ < 10000) {
- X if((r=strcmp(name,tdptr->name))==0) {
- X if(inode) { /* copy over new stat struct */
- X for(i=0, ps=(char *)&st,pd=(char *)&(tdptr->stat);i<sizeof(struct stat);i++)
- X *pd++ = *ps++;
- X /* flag this file as "touched" */
- X tdptr->touched = touch;
- X }
- X done=1; /* file found, move on to next */
- X }
- X else if(r<0 && inode) { /* name < tdptr->name insert before? */
- X if((tdptr->prev) == (struct d_entry *)NULL) {
- X /* insert at top of list */
- X new_entry(&t,name,&st);
- X t->touched = touch;
- X t->next = tdptr;
- X tdptr->prev = t;
- X *dptr = t;
- X done=1;
- X }
- X else if(strcmp(name,tdptr->prev->name)>0) {
- X /* insert above tdptr */
- X new_entry(&t,name,&st);
- X t->touched = touch;
- X tdptr->prev->next = t;
- X t->next = tdptr;
- X t->prev = tdptr->prev;
- X tdptr->prev = t;
- X done=1;
- X }
- X else
- X tdptr = tdptr->prev;
- X }
- X else if(inode) { /* name > tdptr->name insert after? */
- X if((tdptr->next) == (struct d_entry *)NULL) {
- X /* insert at end of list */
- X new_entry(&t,name,&st);
- X t->touched = touch;
- X tdptr->next = t;
- X t->prev = tdptr;
- X done=1;
- X }
- X else if(strcmp(name,tdptr->next->name)<0) {
- X /* insert just below tdptr */
- X new_entry(&t,name,&st);
- X t->touched = touch;
- X t->next = tdptr->next;
- X tdptr->next = t;
- X t->prev = tdptr;
- X t->next->prev = t;
- X done=1;
- X }
- X else
- X tdptr = tdptr->next;
- X }
- X else
- X done=1;
- X }
- X }
- X
- X /* loop through and remove all entries that have a different touch
- X if the touch value doesn't match, then file was removed and the
- X entry in the directory was used by a new filename. */
- X tdptr = *dptr; /* start at top of directory */
- X while(tdptr != (struct d_entry *) NULL) {
- X if((tdptr->touched) != touch) {
- X /* need to remove this entry, see where it's at */
- X if(tdptr == (*dptr)) {
- X /* at the top */
- X *dptr = (*dptr)->next;
- X (*dptr)->prev = (struct d_entry *)NULL;
- X tdptr->next = (struct d_entry *)NULL;
- X free_contents(tdptr);
- X tdptr = *dptr;
- X }
- X else if(tdptr->next == (struct d_entry *)NULL) {
- X /* at the bottom */
- X tdptr->prev->next = (struct d_entry *)NULL;
- X free_contents(tdptr);
- X tdptr = (struct d_entry *) NULL; /* end */
- X }
- X else {
- X /* in the middle somewhere */
- X t = tdptr->next;
- X tdptr->prev->next = tdptr->next;
- X tdptr->next->prev = tdptr->prev;
- X tdptr->next = (struct d_entry *) NULL;
- X free_contents(tdptr);
- X tdptr = t;
- X }
- X }
- X else /* try next entry */
- X tdptr = tdptr->next;
- X }
- X
- X#ifdef BSD
- X closedir(dp);
- X#endif BSD
- X#ifdef SYSTEMV
- X close(fd);
- X#endif SYSTEMV
- X}
- X
- X/* new_entry allocates memory for a new addition to a directory, then
- X** copies in the name and stat structure into the newly allocated structure.
- X** It copies nulls into all of the structure's pointers.
- X**
- X** tex is to be assigned to the address of the new memory.
- X** name is the string to copy into the name field.
- X** st is a pointer to the stat structure to copy over.
- X*/
- new_entry(tex,name,st)
- struct d_entry **tex;
- char *name;
- struct stat *st;
- X{
- X struct d_entry *t;
- X register int i;
- X char *pd, *ps;
- X
- X if((*tex=t= (struct d_entry *) malloc(sizeof(struct d_entry)))==NULL) {
- X clear();
- X printw("OUT OF MEMORY!\n");
- X refresh();
- X ils_exit(1);
- X }
- X t->name = (char *)malloc(strlen(name)+1); /* alloc space for name */
- X strcpy(t->name,name); /* copy name over */
- X
- X for(i=0, ps=(char *)st,pd=(char *)&(t->stat);i<sizeof(struct stat);i++)
- X *pd++ = *ps++; /* copy stat over on byte at a time */
- X
- X t->next = (struct d_entry *) NULL; /* null out all pointers */
- X t->prev = (struct d_entry *) NULL;
- X t->contents = (struct d_entry *) NULL;
- X}
- X
- X/* exit ils gracefully with 'code' as the exit code */
- ils_exit(code)
- int code;
- X{
- X noraw(); /* out of raw mode */
- X echo(); /* echo back on */
- X endwin(); /* exit curses */
- X exit(code);
- X}
- END_OF_FILE
- if test 25940 -ne `wc -c <'ils.c'`; then
- echo shar: \"'ils.c'\" unpacked with wrong size!
- fi
- # end of 'ils.c'
- fi
- if test -f 'ils.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ils.h'\"
- else
- echo shar: Extracting \"'ils.h'\" \(3354 characters\)
- sed "s/^X//" >'ils.h' <<'END_OF_FILE'
- X/* includes for ils program */
- X#ifndef ushort
- X#include <sys/types.h>
- X#endif
- X
- X#ifndef stat_h
- X#include <sys/stat.h>
- X#endif
- X
- X#define ILS_MAX_ENTRIES 1000
- X#define ILS_MAX_PATS 256 /* max search patterns */
- X#define MAX_SYMBOLS 256 /* max symbol table size */
- X
- X/* types of display modes (can be ored if appropriate) */
- X#define ILS_LONG 1 /* long format */
- X#define ILS_ALL 8 /* list ALL files (even . and ..) */
- X#define ILS_F_TYPE 0x10 /* directories end with '/', executables '*' */
- X#define ILS_ECHO_COMS 0x20 /* echo commands as executed */
- X
- X#define ILS_ESCAPE 0x1b /* hard-coded ESCAPE key */
- X#define ILS_ENTER '\n' /* hard-coded RETURN oe ENTER key */
- X#define ILS_RETURN '\r' /* hard-coded RETURN or ENTER key */
- X#define ILS_DOWN 'j' /* hard-coded DOWN */
- X#define ILS_UP 'k' /* hard-coded UP */
- X#define ILS_LEFT 'h' /* hard-coded LEFT */
- X#define ILS_RIGHT 'l' /* hard-coded RIGHT */
- X#define ILS_REDRAW 18 /* control-r */
- X#define ILS_REDRAW_ALT 12 /* control-l */
- X#define ILS_ENV '?' /* display symbol table */
- X#define ILS_FORCE_KEYBOARD ':' /* force keyboard input */
- X#define ILS_EXIT_KEY 4 /* control-d */
- X
- X#define ILS_FILE ".ils" /* ils definition file (per user) */
- X
- X#define ILS_INITIAL -3 /* initial state (only done once) */
- X#define ILS_INITIAL2 -2
- X#define ILS_TOTAL_DRAW -1 /* redraw path, title, and contents */
- X#define ILS_DRAW 0 /* display directory content */
- X#define ILS_KEYBOARD 1 /* get input from keyboard */
- X#define ILS_MOVE_CURSOR 2 /* erase last cursor, show new */
- X#define ILS_SHOW_CURSOR 3 /* redraw the cursor */
- X#define ILS_EXIT 4 /* exit this level of edit_directory */
- X#define ILS_SHOW_PATH 5 /* print the path on the top line */
- X#define ILS_ASCEND 6 /* go up into a new directory */
- X#define ILS_FIND_CURSOR 7 /* figure out best place to put cursor */
- X
- X#ifdef BSD
- X#define flash() addch('\007')
- X#endif
- X
- X#define ILS_METACHAR '$' /* Preceeds all ils variables */
- X#define META1 '/' /* List of sh metacharacters that can be used */
- X#define META2 '<' /* as delimeters. */
- X#define META3 '>'
- X#define META4 '('
- X#define META5 ')'
- X#define META6 '['
- X#define META7 ']'
- X#define META8 '&'
- X#define META9 '|'
- X#define META10 '`'
- X#define META11 '\"'
- X#define META12 '!'
- X#define META13 '~'
- X#define META14 '$'
- X#define META15 '\''
- X#define META16 '?'
- X#define META17 ';'
- X#define META18 '.'
- X
- X#define ILS_MAX_ARGS 256 /* max arguments per single command line */
- X#define MAXPATH 128
- X#define PWD "/bin/pwd"
- X
- X#define BOTTOM 0
- X#define TOP 1
- X
- typedef struct d_entry {
- X char *name;
- X int inode;
- X struct stat stat; /* stat for this file touched */
- X struct d_entry *next; /* next entry in this directory */
- X struct d_entry *prev; /* previous entry in this directory */
- X struct d_entry *contents; /* if a directory, it's contents */
- X long touched; /* flag for last time touched */
- X};
- X
- typedef struct value {
- X char *v;
- X struct value *next;
- X};
- X
- X#define ILS_KEY_SEQUENCE 1
- X#define ILS_VARIABLE 2
- X
- typedef struct symbol {
- X char *name; /* name of this symbol */
- X int type; /* symbol type */
- X struct value *val; /* pointer to symbol value */
- X};
- X
- X#define CURRENT_FILE "file" /* insert this file */
- X#define ALL_FILES "all_files" /* insert all files in directory */
- X#define INPUT "input" /* input from keyboard command */
- X#define PREFIX "prefix" /* insert the prefix (before .) */
- X#define PWD_PATH "path" /* insert the path (ala `pwd`) */
- END_OF_FILE
- if test 3354 -ne `wc -c <'ils.h'`; then
- echo shar: \"'ils.h'\" unpacked with wrong size!
- fi
- # end of 'ils.h'
- fi
- if test -f 'input.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'input.c'\"
- else
- echo shar: Extracting \"'input.c'\" \(5006 characters\)
- sed "s/^X//" >'input.c' <<'END_OF_FILE'
- X#include <curses.h>
- X#include "ils.h"
- X#include "get.h"
- X
- extern int syms; /* number of symbols on symbol table */
- extern struct symbol *symtab[];
- extern char *pnam;
- extern int a_num; /* number of arguments in list */
- extern int a_ind; /* index into current argument */
- extern char *args[ILS_MAX_ARGS];
- extern char cur_path[]; /* pointer to active path */
- extern int modes; /* what special flags might be set */
- X
- process_input(c,list,entry,entries,p,x,y,rx)
- struct d_entry *list[];
- int entry, entries,x,y,rx;
- char p[],c;
- X{
- X struct value *v;
- X char line[256];
- X
- X int i=0;
- X
- X if(c==ILS_FORCE_KEYBOARD) {
- X evaluate_line(line,p,list,entry,entries,x,y,rx);
- X ils_doit(line); /* execute the statement */
- X }
- X else {
- X for(i=0;i<syms;i++)
- X if(strcmp(symtab[i]->name,p)==0){/* found the command */
- X perform_command(!c,symtab[i]->val,list,entry,entries,x,y,rx);
- X break; /* get out of loop */
- X }
- X if(i==syms)
- X flash();
- X }
- X}
- X
- perform_command(c,v,list,entry,entries,x,y,rx)
- struct value *v;
- struct d_entry *list[];
- int entry, entries,x,y,rx;
- X{
- X char line[256];
- X int i;
- X
- X while(v != (struct value *) NULL) {
- X evaluate_line(line,v->v,list,entry,entries,x,y,rx);
- X ils_doit(line); /* execute the statement */
- X v = v->next;
- X }
- X dealloc(args);
- X}
- X
- ils_doit(line)
- char *line;
- X{
- X noraw();
- X echo();
- X clear();
- X if(modes & ILS_ECHO_COMS)
- X printw("%s\n",line);
- X refresh();
- X#ifdef BSD
- X endwin();
- X#endif
- X
- X system(line); /* execute the statement */
- X#ifdef BSD
- X printf("PRESS RETURN TO RETURN TO %s\n",pnam);
- X getchar();
- X initscr();
- X scrollok(stdscr,TRUE);
- X raw();
- X noecho();
- X#endif
- X
- X#ifdef SYSTEMV
- X raw();
- X noecho();
- X standout();
- X printw("Press any key to return to %s",pnam);
- X standend();
- X refresh();
- X getch();
- X#endif SYSTEMV
- X}
- X
- evaluate_line(line,s,list,entry,entries,x,y,rx)
- char s[], line[];
- struct d_entry *list[];
- int entry, entries,x,y,rx;
- X{
- X char c, lable[160], arg[160], new_line[256];
- X register int k;
- X int l, a=0, j, white=0, d, ln=0, i, line_ind=0;
- X
- X l = strlen(s);
- X for(i=0;i<l;i++) {
- X switch(c=s[i]) {
- X case ILS_METACHAR:
- X i++;
- X for(k=d=0;i<l && d==0;i++) {
- X switch(c=s[i]) {
- X case META1: /* possible delimeters */
- X case META2:
- X case META3:
- X case META4:
- X case META5:
- X case META6:
- X case META7:
- X case META8:
- X case META9:
- X case META10:
- X case META11:
- X case META12:
- X case META13:
- X case META14:
- X case META15:
- X case META16:
- X case META17:
- X case META18:
- X case ' ':
- X case '\T':
- X i--;
- X d=1;
- X break;
- X default:
- X lable[k++]=c;
- X break;
- X }
- X }
- X lable[k]='\0';
- X insert_value(new_line,lable,list,entry,entries,s,&i,x,y,rx);
- X i--;
- X for(j=0;new_line[j]!='\0';j++,line_ind++)
- X line[line_ind] = new_line[j];
- X white=0;
- X break;
- X case ' ':
- X case '\t':
- X if(white)
- X break;
- X white=1;
- X line[line_ind++]=' ';
- X break;
- X default:
- X white=0;
- X line[line_ind++]=c;
- X break;
- X }
- X }
- X line[line_ind]='\0';
- X}
- X
- dealloc(args)
- char *args[];
- X{
- X register int i;
- X
- X for(i=0;i<ILS_MAX_ARGS && args[i]!=(char *)NULL;i++)
- X free(args[i]);
- X}
- X
- insert_value(line,lable,list,entry,entries,s,ii,x,y,rx)
- char line[],lable[], s[];
- int *ii,x,y,rx;
- struct d_entry *list[];
- int entry, entries;
- X{
- X char *c, prompt[256], new_prompt[256];
- X register int i, parens, k;
- X int l;
- X
- X if(strcmp(lable,CURRENT_FILE)==0)
- X strcpy(line,list[entry]->name);
- X else if(strcmp(lable,PREFIX)==0) {
- X for(i=0;i<strlen(list[entry]->name) && list[entry]->name[i]!='.';i++)
- X line[i] = list[entry]->name[i];
- X line[i]='\0';
- X }
- X else if(strcmp(lable,PWD_PATH)==0) {
- X for(i=0;cur_path[i]!='\0';i++)
- X line[i] = cur_path[i];
- X line[i]='\0';
- X }
- X else if(strcmp(lable,INPUT)==0) {
- X (*ii)++;
- X for(parens=1,k=0;parens && s[*ii]!='\0';(*ii)++)
- X switch(s[*ii]) {
- X case ')':
- X parens--;
- X if(parens)
- X prompt[k++]=s[*ii];
- X break;
- X case '(':
- X parens++;
- X default:
- X prompt[k++]=s[*ii];
- X break;
- X }
- X if(parens)
- X return(1);
- X prompt[k]='\0';
- X
- X move(y,x);
- X
- X evaluate_line(new_prompt,prompt,list,entry,entries,x,y,rx);
- X l=strlen(new_prompt);
- X printw(new_prompt);
- X line[0]='\0';
- X if(getst(rx-x-l-1,x+l,y,line,rx-x-l,&l,ALL_ALPHA,NULL)!=GET_RETURN)
- X return(1);
- X }
- X#ifdef SYSTEMV
- X else if((c=(char *)getenv(lable))!=NULL)
- X strcpy(line,c);
- X#endif SYSTEMV
- X}
- X
- X/* add to the argument list */
- X/* c is for passing a single character, str is for passing a string,
- X * type==0 for char, 1 for string */
- add_to_args(c,str,type)
- char c, str[];
- int type;
- X{
- X int l,i;
- X
- X if(type) {
- X l=strlen(str);
- X for(i=0;i<l;i++)
- X add_char_to_args(str[i]);
- X }
- X else
- X add_char_to_args(c);
- X}
- X
- add_char_to_args(c)
- char c;
- X{
- X static char line[256];
- X static int line_ind=0;
- X
- X switch(c) {
- X case ' ':
- X case '\t':
- X line[line_ind]='\0';
- X args[a_num] = (char *) malloc(strlen(line)+1);
- X strcpy(args[a_num],line);
- X a_num++;
- X a_ind=0;
- X line_ind=0;
- X break;
- X default:
- X line[line_ind++]=c;
- X if(line_ind>254)
- X line_ind=254;
- X break;
- X }
- X}
- END_OF_FILE
- if test 5006 -ne `wc -c <'input.c'`; then
- echo shar: \"'input.c'\" unpacked with wrong size!
- fi
- # end of 'input.c'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(2923 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X/**************************************************************************
- X** main() routine for ils.
- X**
- X** ils (c) copyright 1991 by Jack Alexander
- X**
- X** NO WARRANTY OF ANY KIND IS ASSOCIATED WITH THIS PROGRAM, NOT EVEN
- X** FOR FITNESS OF PURPOSE
- X**
- X**/
- X#include <curses.h>
- X#include <stdio.h>
- X#include "ils.h"
- X
- char *pnam;
- char *patterns[ILS_MAX_PATS];
- X
- main(argc,argv)
- int argc;
- char *argv[];
- X{
- X int rows=0, cols=0, i, j, pats, modes=0,errs=0,skip,l;
- X char curdir[MAXPATH], *title, c;
- X
- X pnam = argv[0]; /* globnal pointer to program name */
- X title = (char *) NULL; /* no title, yet */
- X
- X /* extract any modes that may be part of a default dure to filename */
- X switch(argv[0][strlen(argv[0])-1]) {
- X case 'a':
- X modes |= ILS_ALL;
- X break;
- X case 'f':
- X modes |= ILS_F_TYPE;
- X break;
- X case 'l':
- X modes |= ILS_LONG;
- X break;
- X }
- X for(i=1,pats=0;i<argc;i++) { /* look at all arguments passed */
- X skip=0;
- X switch(argv[i][0]) {
- X case '-': /* handle the option */
- X l = strlen(argv[i]);
- X for(j=1;j<l;j++) {
- X switch(argv[i][j]) {
- X case 'r':
- X /* change number of rows */
- X j++;
- X c = argv[i][j];
- X while(c>='0' && c<='9' && j<l) {
- X rows *= 10;
- X rows += c-'0';
- X j++;
- X c = argv[i][j];
- X }
- X j--;
- X break;
- X case 'c':
- X /* change number of columns */
- X j++;
- X c = argv[i][j];
- X while(c>='0' && c<='9' && j<l) {
- X cols *= 10;
- X cols += c-'0';
- X j++;
- X c = argv[i][j];
- X }
- X j--;
- X break;
- X case 'a':
- X /* list ALL mode (. files) */
- X modes |= ILS_ALL;
- X break;
- X case 'F':
- X /* show * and / */
- X modes |= ILS_F_TYPE;
- X break;
- X case 'l':
- X /* long listing format */
- X modes |= ILS_LONG;
- X break;
- X case 'e':
- X /* echo commands */
- X modes |= ILS_ECHO_COMS;
- X break;
- X case 'T':
- X /* window to have title */
- X if((i+1)>=argc) {
- X fprintf(stderr,"%s: -T option must be followed with a title\n",pnam);
- X fprintf(stderr," example: %s -T \"This is a title\"\n",pnam);
- X errs++;
- X }
- X else {
- X title = argv[i+1];
- X skip=1;
- X }
- X break;
- X }
- X }
- X break;
- X default:
- X patterns[pats++] = argv[i];
- X }
- X i+=skip;
- X skip=0;
- X }
- X if(errs) {
- X fprintf(stderr,"%s: errors in parameters\n",pnam);
- X exit(0);
- X }
- X patterns[pats] = (char *) NULL;
- X
- X initscr(); /* init curses */
- X scrollok(stdscr,TRUE);
- X if(!rows)
- X rows = LINES;
- X if(!cols)
- X cols = COLS;
- X
- X if(get_curdir(curdir)) {
- X endwin();
- X exit(0);
- X }
- X ils(patterns,curdir,0,0,cols,rows,modes,title);
- X#ifdef BSD
- X clear();
- X printw("Leaving %s...\n",pnam);
- X refresh();
- X#endif
- X endwin(); /* end curses */
- X}
- X
- get_curdir(path)
- char path[];
- X{
- X FILE *fp;
- X
- X if((fp=popen(PWD,"r"))==NULL) {
- X fprintf(stderr,"%s: popen returns error\n",pnam);
- X return(1);
- X };
- X fscanf(fp,"%s",path);
- X pclose(fp);
- X return(0);
- X}
- END_OF_FILE
- if test 2923 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'parse.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parse.c'\"
- else
- echo shar: Extracting \"'parse.c'\" \(3638 characters\)
- sed "s/^X//" >'parse.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include <curses.h>
- X#include "ils.h"
- X
- X#define NUETRAL 0 /* states used in parse */
- X#define IN_OP 1
- X
- extern char *pnam; /* program name */
- extern struct symbol *symtab[]; /* symbol table */
- extern int syms; /* number of symbols on table */
- X
- parse_line(line,lnum)
- char line[];
- int lnum;
- X{
- X static int state=NUETRAL,o,no;
- X char ops[2][160];
- X
- X o=get_opts(ops,line); /* Get the 2 possible parts */
- X
- X if(!o)
- X return(0); /* line was just white space */
- X switch(state) {
- X case NUETRAL:
- X if(o==1) {
- X printw("%s: error on line %d of '%s' file\n",pnam,lnum,ILS_FILE);
- X refresh();
- X return(1);
- X }
- X no=new_op(ops,ILS_KEY_SEQUENCE);
- X state=IN_OP;
- X break;
- X case IN_OP:
- X if(o==2)
- X no=new_op(ops,ILS_KEY_SEQUENCE);
- X else
- X add_op(no,ops);
- X break;
- X default:
- X printw("%s: bad state in parse_line()\n",pnam);
- X refresh();
- X return(1);
- X break;
- X }
- X return(0);
- X}
- X
- X#define ESC 1
- X#define COLON 2
- X#define NEWLINE 3
- X#define SKIP_WHITE 4
- X
- get_opts(s,line)
- char s[2][160], line[];
- X{
- X int i,j,k,l,nonwhite=0,state=0,colons=0;
- X char c;
- X
- X l=strlen(line);
- X s[0][0]=s[1][0]='\0';
- X
- X for(i=j=k=0;i<l;i++) {
- X switch(c=line[i]){
- X case '\\':
- X state=ESC;
- X continue;
- X case '\n':
- X state=NEWLINE;
- X break;
- X case ':':
- X state=COLON;
- X colons++;
- X if(colons==1)
- X break;
- X else
- X state=0;
- X default:
- X if(c==' '||c=='\t')
- X break;
- X nonwhite=1;
- X break;
- X }
- X switch(state) {
- X case ESC:
- X s[j][k]=c;
- X break;
- X case COLON:
- X s[j][k]='\0';
- X j=1;
- X k=0;
- X state=SKIP_WHITE;
- X break;
- X case NEWLINE:
- X s[j][k]='\0';
- X k=0;
- X break;
- X case SKIP_WHITE:
- X if(c==' '||c=='\t')
- X break;
- X else
- X state=0;
- X default:
- X if(!nonwhite) /* skip leading white space */
- X continue;
- X s[j][k++]=c;
- X break;
- X }
- X }
- X if(nonwhite)
- X return(j+1); /* j=0 if one field, j=1 if two fields */
- X else
- X return(0); /* line was all white space */
- X}
- X
- new_op(s,type)
- char s[2][160];
- int type;
- X{
- X struct symbol *t;
- X struct value *v;
- X
- X if(syms==MAX_SYMBOLS) {
- X fprintf(stderr,"%s: symbol table size exceeded\n",pnam);
- X return;
- X }
- X t = symtab[syms] = (struct symbol *) malloc(sizeof(struct d_entry));
- X if(t == NULL) {
- X fprintf(stderr,"%s: out of memory\n",pnam);
- X return;
- X }
- X t->name = (char *)malloc(strlen(s[0])+1);
- X strcpy(t->name,s[0]);
- X t->type = type;
- X
- X if(s[1][0]=='\0')
- X t->val = (struct value *)NULL;
- X else {
- X v = t->val = (struct value *) malloc(sizeof(struct value));
- X v->v = (char *)malloc(strlen(s[1])+1);
- X strcpy(v->v,s[1]);
- X v->next =(struct value *) NULL;
- X }
- X
- X return(syms++);
- X}
- X
- add_op(op,s)
- int op;
- char s[2][160];
- X{
- X struct value *v;
- X
- X v = symtab[op]->val;
- X
- X if(v==(struct value *)NULL) {
- X v = symtab[op]->val = (struct value *) malloc(sizeof(struct value));
- X v->next =(struct value *) NULL;
- X }
- X else {
- X while(v->next != (struct value *)NULL)
- X v = v->next;
- X v->next = (struct value *) malloc(sizeof(struct value));
- X v->next->next = (struct value *) NULL;
- X v = v->next;
- X }
- X v->v = (char *)malloc(strlen(s[0])+1);
- X strcpy(v->v,s[0]);
- X}
- X
- display_symtab()
- X{
- X int i, over=0;
- X struct value *v;
- X
- X for(i=0;i<syms;i++) {
- X clear();
- X standout();
- X printw("Symbol %d: %s\n",i+1,symtab[i]->name);
- X standend();
- X v = symtab[i]->val;
- X while(v!=NULL && over++ != MAX_SYMBOLS) {
- X printw(" %s\n",v->v);
- X v = v->next;
- X }
- X standout();
- X printw("Press RETURN next symbol, %c for previous, ESC to exit",
- X ILS_LEFT);
- X standend();
- X refresh();
- X switch(getch()&0x7f) {
- X case ILS_ENTER:
- X case ILS_RETURN:
- X break;
- X case ILS_LEFT:
- X if(i!=0)
- X i -= 2;
- X else
- X i--;
- X break;
- X case ILS_ESCAPE:
- X return;
- X }
- X }
- X}
- END_OF_FILE
- if test 3638 -ne `wc -c <'parse.c'`; then
- echo shar: \"'parse.c'\" unpacked with wrong size!
- fi
- # end of 'parse.c'
- fi
- if test -f 'wildmat.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wildmat.c'\"
- else
- echo shar: Extracting \"'wildmat.c'\" \(2677 characters\)
- sed "s/^X//" >'wildmat.c' <<'END_OF_FILE'
- X/*
- X** Do shell-style pattern matching for ?, \, [], and * characters.
- X** Might not be robust in face of malformed patterns; e.g., "foo[a-"
- X** could cause a segmentation violation. It is 8bit clean.
- X**
- X** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
- X** Special thanks to Lars Mathiesen for the ABORT code. This can greatly
- X** speed up failing wildcard patterns. For example:
- X** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
- X** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
- X** text 2: -adobe-courier-bold-o-normal--12-120-75-75-p-70-iso8859-1
- X** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
- X** the ABORT, then it takes 22310 calls to fail. Ugh.
- X*/
- X
- X#define TRUE 1
- X#define FALSE 0
- X#define ABORT -1
- X
- static int
- Star(s, p)
- X register char *s;
- X register char *p;
- X{
- X while (wildmat(s, p) == FALSE)
- X if (*++s == '\0')
- X return ABORT;
- X return TRUE;
- X}
- X
- X
- static int
- DoMatch(s, p)
- X register char *s;
- X register char *p;
- X{
- X register int last;
- X register int matched;
- X register int reverse;
- X
- X for ( ; *p; s++, p++) {
- X if (*s == '\0')
- X return ABORT;
- X switch (*p) {
- X case '\\':
- X /* Literal match with following character. */
- X p++;
- X /* FALLTHROUGH */
- X default:
- X if (*s != *p)
- X return FALSE;
- X continue;
- X case '?':
- X /* Match anything. */
- X continue;
- X case '*':
- X /* Trailing star matches everything. */
- X return *++p ? Star(s, p) : TRUE;
- X case '[':
- X /* [^....] means inverse character class. */
- X if (reverse = p[1] == '^')
- X p++;
- X for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
- X /* This next line requires a good C compiler. */
- X if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
- X matched = TRUE;
- X if (matched == reverse)
- X return FALSE;
- X continue;
- X }
- X }
- X
- X return *s == '\0';
- X}
- X
- X
- int
- wildmat(s, p)
- X char *s;
- X char *p;
- X{
- X return DoMatch(s, p) == TRUE;
- X}
- X
- X
- X
- X#ifdef TEST
- X#include <stdio.h>
- X
- X/* Yes, we use gets not fgets. Sue me. */
- extern char *gets();
- X
- X
- main()
- X{
- X char pattern[80];
- X char text[80];
- X
- X printf("Wildmat tester. Enter pattern, then strings to test.\n");
- X printf("A blank line gets prompts for a new pattern; a blank pattern\n");
- X printf("exits the program.\n\n");
- X
- X for ( ; ; ) {
- X printf("Enter pattern: ");
- X if (gets(pattern) == NULL)
- X break;
- X for ( ; ; ) {
- X printf("Enter text: ");
- X if (gets(text) == NULL)
- X exit(0);
- X if (text[0] == '\0')
- X /* Blank line; go back and get a new pattern. */
- X break;
- X printf(" %s\n", wildmat(text, pattern) ? "YES" : "NO");
- X }
- X }
- X
- X exit(0);
- X /* NOTREACHED */
- X}
- X#endif /* TEST */
- END_OF_FILE
- if test 2677 -ne `wc -c <'wildmat.c'`; then
- echo shar: \"'wildmat.c'\" unpacked with wrong size!
- fi
- # end of 'wildmat.c'
- fi
- echo shar: End of shell archive.
- exit 0
-